package top.xia17.plugins.fast.dynamic.datasource;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationAdvisor;
import com.baomidou.dynamic.datasource.aop.DynamicLocalTransactionInterceptor;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import top.xia17.plugins.fast.common.crypto.asymmetric.RsaUtil;
import top.xia17.plugins.fast.common.database.dynamic.DatasourceLoader;
import top.xia17.plugins.fast.common.database.dynamic.DsManager;
import top.xia17.plugins.fast.common.database.dynamic.DsSwitch;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Role;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.transaction.annotation.Transactional;
import top.xia17.plugins.fast.dynamic.datasource.dao.DatasourceRepository;
import top.xia17.plugins.fast.dynamic.datasource.dao.DynamicDatasourceJpaConfig;
import top.xia17.plugins.fast.dynamic.datasource.dao.JpaDatasourceLoader;
import top.xia17.plugins.fast.dynamic.datasource.mgmt.DatasourceMgmtRest;
import top.xia17.plugins.fast.dynamic.datasource.mgmt.DatasourceService;

/**
 * xia17fast多数据源支持的自动配置类
 *
 * @author xia17
 * @date 2022/4/13
 */
@Configuration
@AutoConfigureAfter(DynamicDataSourceAutoConfiguration.class)
@RequiredArgsConstructor
@EnableConfigurationProperties(DynamicDatasourceProperties.class)
@Import(DynamicDatasourceJpaConfig.class)
public class Xia17DynamicDatasourceAutoconfiguration {


    /**
     * 是否开启本地事务
     * 注意如果开启本地事务,需要将spring默认的事务关闭
     * @return /
     */
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    @ConditionalOnProperty(prefix = DynamicDatasourceProperties.PREFIX, name = "local-transaction-enabled", havingValue = "true")
    public DynamicDataSourceAnnotationAdvisor xia17DynamicTransactionAdvisor() {
        DynamicLocalTransactionInterceptor interceptor = new DynamicLocalTransactionInterceptor();
        return new DynamicDataSourceAnnotationAdvisor(interceptor, Transactional.class);
    }

    /**
     * 是否将数据源信息放置在数据库中
     *
     * @return /
     */
    @Bean
    @ConditionalOnProperty(
            prefix = "xia17fast.dynamic-datasource",
            name = {"jpa-enabled"},
            havingValue = "true"
    )
    @ConditionalOnClass(JpaRepositoryFactory.class)
    @ConditionalOnBean(DynamicDatasourceJpaConfig.class)
    public DatasourceLoader datasourceLoader(DatasourceRepository datasourceRepository) {
        return new JpaDatasourceLoader(datasourceRepository);
    }


    /**
     * 数据源管理
     * 这个方法注入的dsManager不具备从数据库获取数据源信息的能力
     *
     * @return /
     */
    @Bean("dsManager")
    @ConditionalOnMissingBean(DatasourceLoader.class)
    @SuppressWarnings("all")
    public DsManager dsManager(DynamicRoutingDataSource dataSource, DefaultDataSourceCreator dataSourceCreator) {
        return new DsManager(dataSource, dataSourceCreator);
    }

    /**
     * 数据源管理
     * 这个方法注入的dsManager具备从数据库获取数据源信息的能力
     *
     * @return /
     */
    @Bean("dsManager")
    @ConditionalOnBean(DatasourceLoader.class)
    @SuppressWarnings("all")
    public DsManager jpaDsManager(DatasourceLoader datasourceLoader,
                                  DynamicRoutingDataSource dataSource,
                                  DefaultDataSourceCreator dataSourceCreator) {
        return new DsManager(dataSource, dataSourceCreator, datasourceLoader);
    }


    /**
     * 数据源动态切换工具
     *
     * @param dsManager /
     * @return /
     */
    @Bean
    @ConditionalOnBean(DsManager.class)
    @SuppressWarnings("all")
    public DsSwitch dsSwitch(DsManager dsManager) {
        return new DsSwitch(dsManager);
    }


    /**
     * 数据源管理API需要的service类
     *
     * @param rsaUtil   rsa加密工具
     * @param dsManager /
     * @return /
     */
    @Bean
    @ConditionalOnBean(DynamicDatasourceJpaConfig.class)
    @ConditionalOnProperty(
            prefix = "xia17fast.dynamic-datasource",
            name = {"mgmt-api-enabled"},
            havingValue = "true"
    )
    @SuppressWarnings("all")
    public DatasourceService datasourceService(RsaUtil rsaUtil, DsManager dsManager) {
        return new DatasourceService(rsaUtil, dsManager);
    }


    /**
     * 数据源管理API接口
     *
     * @param datasourceService /
     * @return /
     */
    @Bean
    @ConditionalOnBean(DatasourceService.class)
    @ConditionalOnProperty(
            prefix = "xia17fast.dynamic-datasource",
            name = {"mgmt-api-enabled"},
            havingValue = "true"
    )
    public DatasourceMgmtRest datasourceMgmtRest(DatasourceService datasourceService) {
        return new DatasourceMgmtRest(datasourceService);
    }





}
